home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / RKMLibsPrgs / graphics_libraries / sprites_bobs / collide.c < prev    next >
C/C++ Source or Header  |  1992-09-03  |  27KB  |  755 lines

  1. ;/*  collide.c - An example of collision detection between objects and between the border.
  2. If EXISTS animtools.c
  3.     LC -b1 -cfist -v -j73 animtools.c  ;  Create AnimTools object file
  4. Else
  5.     Echo "Requires animtools.c (which isn't here) in order to compile."
  6.     Quit
  7. EndIf
  8. LC -b1 -cfist -v -j73 collide.c
  9. Blink FROM LIB:c.o,animtools.o,collide.o TO collide LIBRARY LIB:LC.lib,LIB:Amiga.lib
  10. Quit ;
  11.  
  12.  
  13. Copyright (c) 1992 Commodore-Amiga, Inc.
  14.  
  15. This example is provided in electronic form by Commodore-Amiga, Inc. for
  16. use with the "Amiga ROM Kernel Reference Manual: Libraries", 3rd Edition,
  17. published by Addison-Wesley (ISBN 0-201-56774-1).
  18.  
  19. The "Amiga ROM Kernel Reference Manual: Libraries" contains additional
  20. information on the correct usage of the techniques and operating system
  21. functions presented in these examples.  The source and executable code
  22. of these examples may only be distributed in free electronic form, via
  23. bulletin board or as part of a fully non-commercial and freely
  24. redistributable diskette.  Both the source and executable code (including
  25. comments) must be included, without modification, in any copy.  This
  26. example may not be published in printed form or distributed with any
  27. commercial product.  However, the programming techniques and support
  28. routines set forth in these examples may be used in the development
  29. of original executable software products for Commodore Amiga computers.
  30.  
  31. All other rights reserved.
  32.  
  33. This example is provided "as-is" and is subject to change; no
  34. warranties are made.  All use is at your own risk. No liability or
  35. responsibility is assumed.
  36.  
  37. */
  38.  
  39.  
  40. #include <exec/types.h>
  41. #include <intuition/intuition.h>
  42. #include <intuition/intuitionbase.h>
  43. #include <graphics/gfx.h>
  44. #include <graphics/gfxbase.h>
  45. #include <graphics/gels.h>
  46. #include <graphics/collide.h>
  47. #include <exec/memory.h>
  48. #include <libraries/dos.h>
  49.  
  50. #include "animtools.h"
  51. #include "animtools_proto.h"
  52.  
  53. #include <stdlib.h>
  54. #include <stdio.h>
  55.  
  56. int CXBRK(void) { return(0); }
  57.  
  58. /* prototypes for functions in this file */
  59. VOID __stdargs __saveds hit_routine(struct VSprite *vs1,struct VSprite *vs2);
  60. VOID __stdargs __saveds bounceWall(struct VSprite *vs1,LONG borderflags);
  61. struct AnimOb *setupBoing(SHORT dbufing);
  62. VOID runAnimation(struct Window *win, SHORT dbufing,
  63.                   struct AnimOb **animKey, struct BitMap **myBitMaps);
  64. LONG setupPlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height);
  65. struct BitMap **setupBitMaps(LONG depth, LONG width, LONG height);
  66. VOID freePlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height);
  67. VOID freeBitMaps(struct BitMap **myBitMaps,
  68.                     LONG depth, LONG width, LONG height);
  69. struct GelsInfo *setupDisplay(struct Window **win, SHORT dbufing,
  70.                               struct BitMap **myBitMaps);
  71. VOID drawGels(struct Window *win, struct AnimOb **animKey,
  72.               SHORT dbufing, WORD *toggleFrame, struct BitMap **myBitMaps);
  73.  
  74. #define RBMWIDTH  320
  75. #define RBMHEIGHT 200
  76. #define RBMDEPTH    4
  77.  
  78. struct NewScreen ns =
  79.     {
  80.     0, 0, 320, 200, 2, 0, 1, NULL,
  81.     CUSTOMSCREEN, NULL, "Collision With AnimObs", NULL, NULL
  82.     };
  83. struct NewWindow nw =
  84.     {
  85.     50, 50, 220, 100, -1, -1, CLOSEWINDOW,
  86.     WINDOWCLOSE | RMBTRAP, NULL, NULL, "Close Window to Stop", NULL,
  87.     NULL, 150, 100, 150, 100, CUSTOMSCREEN
  88.     };
  89.  
  90. struct IntuitionBase *IntuitionBase = NULL;
  91. struct GfxBase       *GfxBase       = NULL;
  92.  
  93. int return_code;
  94.  
  95. /* these give the number of frames (COUNT), size (HEIGHT, WIDTH, DEPTH),
  96. ** and word width (WWIDTH) of the animated object.
  97. */
  98. #define BOING_COUNT     6
  99. #define BOING_HEIGHT    25
  100. #define BOING_WIDTH     32
  101. #define BOING_DEPTH      1
  102. #define BOING_WWIDTH    ((BOING_WIDTH + 15) / 16)
  103.  
  104. /* these are the IDs for the system to use for the three objects.
  105. ** these numbers will be used for the collision detection system.
  106. **
  107. ** Do not use zero (0), as it is reserved by the collision system
  108. ** for border hits (see graphics/collide.h, BORDERHIT.)
  109. */
  110. #define BOING_1     2
  111. #define BOING_2     3
  112. #define BOING_3     4
  113.  
  114. /* these are the number of counts that each frame is displayed.
  115. ** they are all one, so each frame is displayed once then the
  116. ** animation system will move on to the next in the sequence
  117. */
  118. SHORT boing3Times[BOING_COUNT] = { 1, 1, 1, 1, 1, 1 };
  119.  
  120. /* these are all set to zero as we do not want anything added
  121. ** to the X and Y positions using ring motion control.
  122. ** all movement is done using the acceleration and velocity
  123. ** values.
  124. */
  125. SHORT boing3YTranses[BOING_COUNT] = { 0, 0, 0, 0, 0, 0 };
  126. SHORT boing3XTranses[BOING_COUNT] = { 0, 0, 0, 0, 0, 0 };
  127.  
  128. /* no special routines to call when each anim comp is displayed */
  129. WORD (*boing3CRoutines[BOING_COUNT])(struct AnimComp *) =
  130.     { NULL, NULL, NULL, NULL, NULL, NULL };
  131.  
  132. UWORD __chip boing3Image[BOING_COUNT][BOING_WWIDTH * BOING_HEIGHT * BOING_DEPTH]
  133. =
  134.     {
  135.     /*----- bitmap Boing, frame 0:  w = 32, h = 25 ------ */
  136.         {
  137.         0x0023, 0x0000,  0x004E, 0x3000,  0x00E3, 0x3A00,  0x03C3, 0xC900,
  138.         0x0787, 0x8780,  0x108F, 0x8700,  0x31F7, 0x8790,  0x61F0, 0x4790,
  139.         0x63E0, 0xFB90,  0x43E0, 0xF848,  0x3BC0, 0xF870,  0x3801, 0xF870,
  140.         0x383D, 0xF070,  0x387E, 0x1070,  0x387C, 0x0EE0,  0xD87C, 0x1F10,
  141.         0x467C, 0x1E10,  0x479C, 0x1E30,  0x6787, 0x3E20,  0x0787, 0xCC60,
  142.         0x0F0F, 0x8700,  0x048F, 0x0E00,  0x0277, 0x1C00,  0x0161, 0xD800,
  143.         0x0027, 0x2000,
  144.         },
  145.     /*----- bitmap Boing, frame 1:  w = 32, h = 25 ------ */
  146.         {
  147.         0x0031, 0x8000,  0x0107, 0x1800,  0x00F0, 0x1900,  0x09E1, 0xEC80,
  148.         0x13C1, 0xE340,  0x1803, 0xE380,  0x387B, 0xC390,  0x30F8, 0x01D0,
  149.         0x70F8, 0x3DC0,  0xE1F0, 0x3E08,  0x9DF0, 0x7C30,  0x9E30, 0x7C30,
  150.         0x9E1C, 0x7C30,  0x1C1F, 0x9C30,  0x1C1F, 0x0630,  0x7C1F, 0x0780,
  151.         0x623F, 0x0798,  0x63DE, 0x0F10,  0x23C1, 0x0F20,  0x33C3, 0xEE20,
  152.         0x0BC3, 0xC380,  0x0647, 0xC700,  0x023F, 0x8E00,  0x0130, 0xF800,
  153.         0x0033, 0x8000,
  154.         },
  155.     /*----- bitmap Boing, frame 2:  w = 32, h = 25 ------ */
  156.         {
  157.         0x0019, 0xC000,  0x0103, 0x8800,  0x0278, 0x8D00,  0x0CF0, 0xFE80,
  158.         0x11F0, 0xF140,  0x0E60, 0xF1E0,  0x1C39, 0xF0C0,  0x1C3E, 0x30C0,
  159.         0x387E, 0x0CE0,  0xF87C, 0x1F28,  0x8C7C, 0x1F18,  0x8F3C, 0x1F18,
  160.         0x8F06, 0x1E18,  0x8F07, 0xDE18,  0x8F07, 0xC018,  0x6E0F, 0xC1C0,
  161.         0x300F, 0x83C8,  0x31EF, 0x8390,  0x31F0, 0x8780,  0x11E0, 0xF720,
  162.         0x11E1, 0xF1C0,  0x0B61, 0xE300,  0x071B, 0xC600,  0x0138, 0x6C00,
  163.         0x0031, 0x8000,
  164.         },
  165.     /*----- bitmap Boing, frame 3:  w = 32, h = 25 ------ */
  166.         {
  167.         0x001C, 0xE000,  0x01B1, 0xCC00,  0x031C, 0xC500,  0x0C3C, 0x3680,
  168.         0x1878, 0x7840,  0x2F70, 0x78E0,  0x0E08, 0x7860,  0x1E0F, 0xB860,
  169.         0x1C1F, 0x0460,  0xBC1F, 0x07B0,  0xC43F, 0x0788,  0xC7FE, 0x0788,
  170.         0xC7C0, 0x0F88,  0xC781, 0xEF88,  0xC783, 0xF118,  0x2783, 0xE0E8,
  171.         0x3983, 0xE1E0,  0x3863, 0xE1C0,  0x1878, 0xC1C0,  0x3878, 0x3380,
  172.         0x10F0, 0x78C0,  0x0B70, 0xF180,  0x0588, 0xE200,  0x009E, 0x2400,
  173.         0x0018, 0xC000,
  174.         },
  175.     /*----- bitmap Boing, frame 4:  w = 32, h = 25 ------ */
  176.         {
  177.         0x000E, 0x6000,  0x00F8, 0xE400,  0x030F, 0xE600,  0x061E, 0x1300,
  178.         0x0C3E, 0x1C80,  0x27FC, 0x1C60,  0x0784, 0x3C60,  0x4F07, 0xFE20,
  179.         0x8F07, 0xC230,  0x1E0F, 0xC1F0,  0x620F, 0x83C8,  0x61CF, 0x83C8,
  180.         0x61E1, 0x83C8,  0x63E0, 0x63C8,  0x63E0, 0xF9C8,  0x03E0, 0xF878,
  181.         0x1DC0, 0xF860,  0x1C21, 0xF0E0,  0x5C3E, 0xF0C0,  0x0C3C, 0x11C0,
  182.         0x143C, 0x3C40,  0x09B8, 0x3880,  0x05C0, 0x7000,  0x00CF, 0x0400,
  183.         0x000C, 0x6000,
  184.         },
  185.     /*----- bitmap Boing, frame 5:  w = 32, h = 25 ------ */
  186.         {
  187.         0x0026, 0x2000,  0x00FC, 0x7400,  0x0187, 0x7200,  0x030F, 0x0100,
  188.         0x0E0F, 0x0E80,  0x319F, 0x0E00,  0x23C6, 0x0F30,  0x63C1, 0xCF30,
  189.         0x4781, 0xF310,  0x0783, 0xE0D0,  0x7383, 0xE0E0,  0x70C3, 0xE0E0,
  190.         0x70F9, 0xE1E0,  0x70F8, 0x21E0,  0x70F8, 0x3FE0,  0x91F0, 0x3E38,
  191.         0x4FF0, 0x7C30,  0x4E10, 0x7C60,  0x4E0F, 0x7860,  0x2E1F, 0x08C0,
  192.         0x0E1E, 0x0E00,  0x049E, 0x1C80,  0x00E4, 0x3800,  0x00C7, 0x9000,
  193.         0x000E, 0x6000,
  194.         }
  195.     };
  196.  
  197. /* these structures contain the initialization data for the animation
  198. ** sequence.
  199. */
  200. NEWBOB newBoingBob =
  201.     {
  202.     NULL, BOING_WWIDTH, BOING_HEIGHT, BOING_DEPTH, 0x2, 0x0,
  203.     SAVEBACK | OVERLAY, 0, RBMDEPTH, 0,0,0,0,
  204.     };
  205. NEWANIMSEQ newBoingSeq =
  206.     {
  207.     NULL, (WORD *)boing3Image, boing3XTranses, boing3YTranses,
  208.     boing3Times, boing3CRoutines, 0, BOING_COUNT, 0,
  209.     };
  210.  
  211. /*-------------------------------------------------------------------------
  212. ** setupBoing()
  213. **
  214. ** make a new animation object.  since all of the boing balls use the same
  215. ** underlying data, the initalization structures are hard-coded into the
  216. ** routine (newBoingBob and newBoingSeq.)
  217. **
  218. ** return a pointer to the object if successful, NULL if failure.
  219. ** set a global error code on failure.
  220. */
  221. struct AnimOb *setupBoing(SHORT dbufing)
  222. {
  223. struct AnimOb   *bngOb;
  224. struct AnimComp *bngComp;
  225.  
  226. if (NULL != (bngOb = AllocMem((LONG)sizeof(struct AnimOb), MEMF_CLEAR)))
  227.     {
  228.     newBoingBob.nb_DBuf    = dbufing;     /* double-buffer status  */
  229.     newBoingSeq.nas_HeadOb = bngOb;       /* pass down head object */
  230.  
  231.     if (NULL != (bngComp = makeSeq(&newBoingBob, &newBoingSeq)))
  232.         {
  233.         bngOb->HeadComp = bngComp;  /* the head comp is the one that */
  234.                                     /* is returned by makeSeq()      */
  235.         return(bngOb);
  236.         }
  237.     FreeMem(bngOb, (LONG)sizeof(struct AnimOb));
  238.     }
  239. return_code = RETURN_WARN;
  240. return(NULL);
  241. }
  242.  
  243. /*-------------------------------------------------------------------------
  244. ** runAnimation()
  245. **
  246. ** a simple message handling loop that also draws the successive frames.
  247. */
  248. VOID runAnimation(struct Window *win, SHORT dbufing,
  249.                   struct AnimOb **animKey, struct BitMap **myBitMaps)
  250. {
  251. struct IntuiMessage  *intuiMsg;
  252. WORD toggleFrame;
  253.  
  254. /* toggleFrame is used to keep track of which frame of the double buffered
  255. ** screen we are currently displaying.  the variable must exist for the life
  256. ** of the displayed objects, so it is defined here.
  257. */
  258. toggleFrame = 0;
  259.  
  260. /* end the loop on a CLOSEWINDOW event */
  261. for (;;)
  262.     {
  263.     /* draw the gels, then check for messages.
  264.     ** check the messages after each display so we get a quick response.
  265.     */
  266.     drawGels(win, animKey, dbufing, &toggleFrame, myBitMaps);
  267.  
  268.     /* quit on a control_c */
  269.     if (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  270.         return;
  271.  
  272.     /* check for a closewindow event, die if found */
  273.     while (intuiMsg = (struct IntuiMessage *)GetMsg(win->UserPort))
  274.         {
  275.         if (intuiMsg->Class == CLOSEWINDOW)
  276.             {
  277.             ReplyMsg((struct Message *)intuiMsg);
  278.             return;
  279.             }
  280.         ReplyMsg((struct Message *)intuiMsg);
  281.         }
  282.     }
  283. }
  284.  
  285. /*-------------------------------------------------------------------------
  286. ** setupPlanes()
  287. **
  288. ** called only for double-buffered displays.
  289. ** allocate and clear each bit-plane in a bitmap structure.
  290. ** clean-up on failure.
  291. */
  292. LONG setupPlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height)
  293. {
  294. SHORT plane_num ;
  295.  
  296. for (plane_num = 0; plane_num < depth; plane_num++)
  297.     {
  298.     if (NULL != (bitMap->Planes[plane_num] =
  299.                     (PLANEPTR)AllocRaster(width, height)))
  300.         BltClear((APTR)(bitMap->Planes[plane_num]), (width / 8) * height, 1);
  301.     else
  302.         {
  303.         freePlanes(bitMap, depth, width, height);
  304.         return_code = RETURN_WARN;
  305.         return(NULL);
  306.         }
  307.     }
  308. return(TRUE);
  309. }
  310.  
  311. /*-------------------------------------------------------------------------
  312. ** setupBitMaps()
  313. **
  314. ** allocate the two bitmaps for a double-buffered display.
  315. ** routine only called when the display is double-buffered.
  316. */
  317. struct BitMap **setupBitMaps(LONG depth, LONG width, LONG height)
  318. {
  319. static struct BitMap *myBitMaps[2];
  320.  
  321. /* allocate the two bit-map structures. these do not have to be in CHIP */
  322. if (NULL != (myBitMaps[0] =
  323.         (struct BitMap *)AllocMem((LONG)sizeof(struct BitMap), MEMF_CLEAR)))
  324.     {
  325.     if (NULL != (myBitMaps[1] =
  326.         (struct BitMap *)AllocMem((LONG)sizeof(struct BitMap), MEMF_CLEAR)))
  327.         {
  328.         /* initialize the bit maps to the correct size. */
  329.         InitBitMap(myBitMaps[0], (BYTE)depth, (SHORT)width, (SHORT)height);
  330.         InitBitMap(myBitMaps[1], (BYTE)depth, (SHORT)width, (SHORT)height);
  331.  
  332.         /* allocate and initialize the bit-planes for the bit-maps. */
  333.         if (NULL != setupPlanes(myBitMaps[0], depth, width, height))
  334.             {
  335.             if (NULL != setupPlanes(myBitMaps[1], depth, width, height))
  336.                 return(myBitMaps);
  337.  
  338.             freePlanes(myBitMaps[0], depth, width, height);
  339.             }
  340.         FreeMem(myBitMaps[1], (LONG)sizeof(struct BitMap));
  341.         }
  342.     FreeMem(myBitMaps[0], (LONG)sizeof(struct BitMap));
  343.     }
  344. /* on failure, everything is freed and a global return code is set. */
  345. return_code = RETURN_WARN;
  346. return(NULL);
  347. }
  348.  
  349. /*-------------------------------------------------------------------------
  350. ** freePlanes()
  351. **
  352. ** free all of the bit-planes in a bit-map structure.
  353. */
  354. VOID freePlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height)
  355. {
  356. SHORT plane_num ;
  357.  
  358. for (plane_num = 0; plane_num < depth; plane_num++)
  359.     {
  360.     if (NULL != bitMap->Planes[plane_num])
  361.         FreeRaster(bitMap->Planes[plane_num], (USHORT)width, (USHORT)height);
  362.     }
  363. }
  364.  
  365. /*-------------------------------------------------------------------------
  366. ** freeBitMaps()
  367. **
  368. ** free the two bit-maps from the double buffered display.
  369. ** the bit-planes are freed first, then the bit-map structures.
  370. */
  371. VOID freeBitMaps(struct BitMap **myBitMaps, LONG depth, LONG width, LONG height)
  372. {
  373. freePlanes(myBitMaps[0], depth, width, height);
  374. freePlanes(myBitMaps[1], depth, width, height);
  375.  
  376. FreeMem(myBitMaps[0], (LONG)sizeof(struct BitMap));
  377. FreeMem(myBitMaps[1], (LONG)sizeof(struct BitMap));
  378. }
  379.  
  380. /*-------------------------------------------------------------------------
  381. ** setupDisplay()
  382. **
  383. ** open the screen and the window for the display.
  384. **
  385. ** if using double buffered display, assume the bit-maps have been opened
  386. ** and correctly set-up.
  387. */
  388. struct GelsInfo *setupDisplay(struct Window **win, SHORT dbufing,
  389.                               struct BitMap **myBitMaps)
  390. {
  391. struct GelsInfo    *gInfo;
  392. struct Screen      *screen;
  393.  
  394. /* if double-buffered, set-up the new screen structure for custom bit map */
  395. if (dbufing)
  396.     {
  397.     ns.Type |= CUSTOMBITMAP;
  398.     ns.CustomBitMap = myBitMaps[0];
  399.     }
  400.  
  401. /* open everything.  check for failure. */
  402. if ((screen = (struct Screen *)OpenScreen(&ns)) != NULL)
  403.     {
  404.     nw.Screen = screen;
  405.     if ((*win = (struct Window *)OpenWindow(&nw)) != NULL)
  406.         {
  407.         if (dbufing)
  408.             {
  409.             /* we are double buffered.  set the rastport for it. */
  410.             (*win)->WScreen->RastPort.Flags = DBUFFER;
  411.  
  412.             /* this copies the intuition display (close gadget) to the
  413.             ** second bit-map so the display does not flash when we change
  414.             ** between them.
  415.             */
  416.             (*win)->WScreen->RastPort.BitMap = myBitMaps[1];
  417.             BltBitMapRastPort(myBitMaps[0], 0,0, &(*win)->WScreen->RastPort,
  418.                         0,0, RBMWIDTH, RBMHEIGHT, 0xC0);
  419.             (*win)->WScreen->RastPort.BitMap = myBitMaps[0];
  420.             }
  421.  
  422.         /* ready the gel system for accepting objects
  423.         ** this is only done once for each rastport in use.
  424.         */
  425.         if (NULL != (gInfo = setupGelSys(&(*win)->WScreen->RastPort, 0x03)))
  426.             return(gInfo);
  427.  
  428.         CloseWindow(*win);
  429.         }
  430.     CloseScreen(screen);
  431.     }
  432. /* on an error everything is cleaned-up, and a global return code is set. */
  433. return_code = RETURN_WARN;
  434. return(NULL);
  435. }
  436.  
  437. /*-------------------------------------------------------------------------
  438. ** drawGels()
  439. **
  440. ** handle the update of the display.  Animate the simulation and check for
  441. ** collisions.  If the screen is double buffered, swap the bit map as
  442. ** required.
  443. */
  444. VOID drawGels(struct Window *win, struct AnimOb **animKey, SHORT dbufing,
  445.               WORD *toggleFrame, struct BitMap **myBitMaps)
  446. {
  447. /* do the required animation stuff.  you must sort both after the animate
  448. ** call and after the collision call.
  449. */
  450. Animate((struct AnimOb **)animKey, &win->WScreen->RastPort);
  451. SortGList(&win->WScreen->RastPort);
  452.  
  453. DoCollision(&win->WScreen->RastPort);
  454. SortGList(&win->WScreen->RastPort);
  455.  
  456. /* toggle if double buffered */
  457. if (dbufing)
  458.     win->WScreen->ViewPort.RasInfo->BitMap = myBitMaps[*toggleFrame];
  459.  
  460. /* draw the new position of the gels into the screen. */
  461. DrawGList(&win->WScreen->RastPort, &win->WScreen->ViewPort);
  462.  
  463. /* if using a double buffered display, you have a more complicated
  464. ** update procedure.
  465. **
  466. ** if not, then simply use WaitTOF().
  467. */
  468. if (dbufing)
  469.     {
  470.     MakeScreen(win->WScreen);
  471.     RethinkDisplay();
  472.  
  473.     *toggleFrame ^= 1;
  474.     win->WScreen->RastPort.BitMap = myBitMaps[*toggleFrame];
  475.     }
  476. else
  477.     WaitTOF();
  478. }
  479.  
  480. /*-------------------------------------------------------------------------
  481. ** bounceWall()
  482. **
  483. ** handle bouncing the animation objects off of the walls.
  484. **
  485. ** use __stdargs and __saveds because this routine is not directly called
  486. ** by this program.  The call to DoCollision() causes a call back to
  487. ** this routine when an animation object comes in contact with a wall.
  488. ** __stdargs says the arguments are passed on the stack.
  489. ** __saveds says to restore the data segment pointer on entry to the routine.
  490. */
  491. VOID __stdargs __saveds bounceWall(struct VSprite *vs1,LONG borderflags)
  492. {
  493. struct AnimOb *ob;
  494.  
  495. /* get a pointer to the object from the sprite pointer. */
  496. ob = vs1->VSBob->BobComp->HeadOb;
  497.  
  498. /* check for hits and act apropriately.
  499. ** for right and left, reverse the x velocity if the object is moving
  500. ** towards the wall (it may have already reversed but still be in contact
  501. ** with the wall.)
  502. ** for the bottom and top you also have to subtract out the velocity.
  503. */
  504. if (((borderflags & RIGHTHIT) && (ob->XVel > 0)) ||
  505.     ((borderflags & LEFTHIT) && (ob->XVel < 0)))
  506.     ob->XVel = -(ob->XVel);
  507. else if (((borderflags & TOPHIT) && (ob->YVel < 0)) ||
  508.          ((borderflags & BOTTOMHIT) && (ob->YVel > 0)))
  509.     {
  510.     ob->YVel -= ob->YAccel;
  511.     ob->YVel = -(ob->YVel);
  512.     }
  513. }
  514.  
  515. /*-------------------------------------------------------------------------
  516. ** hit_routine()
  517. **
  518. ** handle the collision between two animation objects.
  519. ** this routine simulates objects bouncing off of each other.
  520. ** this does not do a very good job of it, it does not take into account
  521. ** the angle of the collision or real physics.
  522. ** if anyone wants to fix it, please feel free.
  523. **
  524. ** use __stdargs and __saveds because this routine is not directly called
  525. ** by this program.  The call to DoCollision() causes a call back to
  526. ** this routine when two animation objects overlap.
  527. ** __stdargs says the arguments are passed on the stack.
  528. ** __saveds says to restore the data segment pointer on entry to the routine.
  529. */
  530. VOID __stdargs __saveds hit_routine(struct VSprite *vs1,struct VSprite *vs2)
  531. {
  532. LONG vel1, vel2;
  533.  
  534. /* check that the bob is not being removed!  This is due to a 1.3 bug
  535. ** where all bobs are tested for collision, even the ones that are in
  536. ** the process of being removed.  See text for more information.
  537. **
  538. ** bobs are moved to a very large negative position as they are being
  539. ** removed.  if the BOBSAWAY flag is set, then both bobs in the collision
  540. ** are in the process of being removed--don't do anything in the collision
  541. ** routine.
  542. */
  543. if (!(vs1->VSBob->Flags & BOBSAWAY))
  544.     {
  545.     /* cache the velocity values
  546.     ** Do the X values first (order is not important.)
  547.     */
  548.     vel1 = vs1->VSBob->BobComp->HeadOb->XVel;
  549.     vel2 = vs2->VSBob->BobComp->HeadOb->XVel;
  550.  
  551.     /* if the two objects are moving in the opposite direction (X component)
  552.     ** then negate the velocities.
  553.     ** else swap the velocities.
  554.     */
  555.     if (((vel1 > 0) && (vel2 < 0)) || ((vel1 < 0) && (vel2 > 0)))
  556.         {
  557.         vs1->VSBob->BobComp->HeadOb->XVel = -vel1;
  558.         vs2->VSBob->BobComp->HeadOb->XVel = -vel2;
  559.         }
  560.     else
  561.         {
  562.         vs1->VSBob->BobComp->HeadOb->XVel = vel2;
  563.         vs2->VSBob->BobComp->HeadOb->XVel = vel1;
  564.         }
  565.  
  566.     /* cache the velocity values
  567.     ** Do the Y values second (order is not important.)
  568.     */
  569.     vel1 = vs1->VSBob->BobComp->HeadOb->YVel;
  570.     vel2 = vs2->VSBob->BobComp->HeadOb->YVel;
  571.  
  572.     /* if the two objects are moving in the opposite direction (Y component)
  573.     ** then negate the velocities.
  574.     ** else swap the velocities.
  575.     */
  576.     if (((vel1 > 0) && (vel2 < 0)) || ((vel1 < 0) && (vel2 > 0)))
  577.         {
  578.         vs1->VSBob->BobComp->HeadOb->YVel = -vel1;
  579.         vs2->VSBob->BobComp->HeadOb->YVel = -vel2;
  580.         }
  581.     else
  582.         {
  583.         vs1->VSBob->BobComp->HeadOb->YVel = vel2;
  584.         vs2->VSBob->BobComp->HeadOb->YVel = vel1;
  585.         }
  586.     }
  587. }
  588.  
  589. /*-------------------------------------------------------------------------
  590. ** main routine
  591. **
  592. ** run a double buffered display if the user puts any arguments on the
  593. ** command line.
  594. **
  595. ** open libraries, set-up the display, set-up the animation system and
  596. ** the objects, set-up collisions between objects and against walls,
  597. ** and run the thing.
  598. **
  599. ** clean-up and close resources when done.
  600. */
  601. VOID main(int argc, char **argv)
  602. {
  603. struct BitMap   **myBitMaps;
  604. struct AnimOb    *boingOb;
  605. struct AnimOb    *boing2Ob;
  606. struct AnimOb    *boing3Ob;
  607. struct Window    *win;
  608. struct Screen    *screen;
  609. struct GelsInfo  *gInfo;
  610. struct AnimOb    *animKey;
  611. SHORT dbufing;
  612.  
  613. return_code = RETURN_OK;
  614.  
  615. /* if any arguments, use double-buffering */
  616. if (argc > 1)
  617.     dbufing = 1;
  618. else
  619.     {
  620.     dbufing = 0;
  621.     if (argc)
  622.         printf("Program will run double buffered if there are\nany command line arguments.\n");
  623.     }
  624.  
  625.  
  626. /* open required libraries */
  627. if (NULL == (IntuitionBase = (struct IntuitionBase *)
  628.         OpenLibrary(INTUITIONNAME, 34L)))
  629.     return_code = RETURN_FAIL;
  630. else
  631.     {
  632.     if (NULL == (GfxBase = (struct GfxBase *)
  633.             OpenLibrary(GRAPHICSNAME, 34L)))
  634.         return_code = RETURN_FAIL;
  635.     else
  636.         {
  637.         /* note that setupBitMaps() will only be called if
  638.         ** we are double buffering
  639.         */
  640.         if ((!dbufing) ||
  641.             (NULL != (myBitMaps=setupBitMaps(RBMDEPTH,RBMWIDTH,RBMHEIGHT))))
  642.             {
  643.             if (NULL != (gInfo = setupDisplay(&win,dbufing,myBitMaps)))
  644.                 {
  645.                 /* you have to initialize the animation key
  646.                 ** before you use it.
  647.                 */
  648.                 InitAnimate(&animKey);
  649.  
  650.                 /* set-up the first boing ball.
  651.                 ** all of these use the same data, hard coded into setupBoing().
  652.                 ** change the color by changing PlanePick.
  653.                 ** set the ID of the ball (MeMask) to BOING_1.
  654.                 ** HitMask = 0xFF means that it will collide with everything.
  655.                  */
  656.                 newBoingBob.nb_PlanePick = 0x2;
  657.                 newBoingBob.nb_MeMask    = 1L<<BOING_1;
  658.                 newBoingBob.nb_HitMask   = 0xFF;
  659.                 if (NULL != (boingOb = setupBoing(dbufing)))
  660.                     {
  661.                     /* pick an initial position, velocity and acceleration
  662.                     ** and add the object to the system.  NOTE that the
  663.                     ** Y-velocity and X-acceleration are not set (they default
  664.                     ** to zero.)  This means that the objects will maintain
  665.                     ** a constant movement to the left or right, and will
  666.                     ** rely on the Y accelleration for the downward movement.
  667.                     ** The collision routines change these values, producing
  668.                     ** bouncing off of walls and other objects.
  669.                     **
  670.                     ** NOTE:  ANFRACSIZE is a value that shifts animation
  671.                     ** constants past an internal decimal point.  If you
  672.                     ** do not do this, then the values will only be some
  673.                     ** fraction of what you expect.  See the text of the
  674.                     ** Animation chapter.
  675.                     */
  676.                     boingOb->AnY    = 10 << ANFRACSIZE;
  677.                     boingOb->AnX    = 250 << ANFRACSIZE;
  678.                     boingOb->XVel   = -(3 << ANFRACSIZE);
  679.                     boingOb->YAccel = 35;
  680.                     AddAnimOb(boingOb, (APTR)&animKey,
  681.                                 &win->WScreen->RastPort);
  682.  
  683.                     /* do the second object--see above comments. */
  684.                     newBoingBob.nb_PlanePick = 0x1;
  685.                     newBoingBob.nb_MeMask    = 1L<<BOING_2;
  686.                     newBoingBob.nb_HitMask   = 0xFF;
  687.                     if (NULL != (boing2Ob = setupBoing(dbufing)))
  688.                         {
  689.                         boing2Ob->AnY    = 50 << ANFRACSIZE;
  690.                         boing2Ob->AnX    = 50 << ANFRACSIZE;
  691.                         boing2Ob->XVel   = 2 << ANFRACSIZE;
  692.                         boing2Ob->YAccel = 35;
  693.                         AddAnimOb(boing2Ob, (APTR)&animKey,
  694.                                 &win->WScreen->RastPort);
  695.  
  696.                         /* do the second object--see above comments.
  697.                         ** here we also use PlaneOnOff to change the color.
  698.                         */
  699.                         newBoingBob.nb_PlanePick = 0x1;
  700.                         newBoingBob.nb_PlaneOnOff= 0x2;
  701.                         newBoingBob.nb_MeMask    = 1L<<BOING_3;
  702.                         newBoingBob.nb_HitMask   = 0xFF;
  703.                         if (NULL != (boing3Ob = setupBoing(dbufing)))
  704.                             {
  705.                             boing3Ob->AnY    = 80 << ANFRACSIZE;
  706.                             boing3Ob->AnX    = 150<< ANFRACSIZE;
  707.                             boing3Ob->XVel   = 1 << ANFRACSIZE;
  708.                             boing3Ob->YAccel = 35;
  709.                             AddAnimOb(boing3Ob, (APTR)&animKey,
  710.                                     &win->WScreen->RastPort);
  711.  
  712.                             /* set up the collisions between boing balls.
  713.                             ** NOTE that they all call the same routine.
  714.                             */
  715.                             SetCollision(BOING_1,hit_routine,gInfo);
  716.                             SetCollision(BOING_2,hit_routine,gInfo);
  717.                             SetCollision(BOING_3,hit_routine,gInfo);
  718.  
  719.                             /* set the collisions with the walls. */
  720.                             SetCollision(BORDERHIT,
  721.                                              (VOID(*)(struct VSprite *, APTR))bounceWall,
  722.                                              gInfo);
  723.  
  724.                             /* everything set-up...run the animation. */
  725.                             runAnimation(win, dbufing, &animKey, myBitMaps);
  726.  
  727.                             /* done...
  728.                             ** free-up everything and clean up the mess.
  729.                              */
  730.                             freeOb(boing3Ob, RBMDEPTH);
  731.                             }
  732.                         freeOb(boing2Ob, RBMDEPTH);
  733.                         }
  734.                     freeOb(boingOb, RBMDEPTH);
  735.                     }
  736.  
  737.                 cleanupGelSys(gInfo, &win->WScreen->RastPort);
  738.                 screen = win->WScreen;
  739.                 CloseWindow(win);
  740.                 CloseScreen(screen);
  741.                 }
  742.  
  743.             if (dbufing)
  744.                 freeBitMaps(myBitMaps, RBMDEPTH, RBMWIDTH, RBMHEIGHT);
  745.             }
  746.         CloseLibrary((struct Library *)GfxBase);
  747.         }
  748.     CloseLibrary((struct Library *)IntuitionBase);
  749.     }
  750.  
  751. /* return the global return code to the system. */
  752. exit(return_code);
  753. }
  754.  
  755.